package com.rabbit.config;

import com.rabbit.route.RoutingKey;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author yuhuan
 * @date 2025/4/18
 */
@Configuration
public class MqProducerConfig {

    @Autowired
    private MqProducerProperties mqProperties;


    @Bean
    public Queue userQueue() {
        // 创建一个持久化的用户同步队列
        return new Queue(mqProperties.getSyncUserQueueName(), true);
    }

    @Bean
    public Queue roomQueue() {
        // 创建一个持久化的房间同步队列
        return new Queue(mqProperties.getSyncRoomQueueName(), true);
    }

    @Bean
    public Queue deviceQueue() {
        // 创建一个持久化的设备同步队列
        return new Queue(mqProperties.getSyncDeviceQueueName(), true);
    }

    @Bean
    public Queue hotelQueue() {
        // 创建一个非持久化的酒店通知队列
        return new Queue(mqProperties.getNoticeHotelQueueName());
    }

    @Bean
    public Queue adminQueue() {
        // 创建一个非持久化的管理员通知队列
        return new Queue(mqProperties.getNoticeAdminQueueName());
    }

    @Bean
    public DirectExchange syncExchange() {
        // 创建一个持久化的直接交换机，用来发送同步消息；并且将交换机设置为非自动删除
        return new DirectExchange(mqProperties.getSyncExchangeName(), true, false);
    }

    @Bean
    public FanoutExchange noticeExchange() {
        // 创建一个非持久化的广播交换机，用来发送通知消息
        return new FanoutExchange(mqProperties.getNoticeExchangeName());
    }

    @Bean
    public TopicExchange topicExchange() {
        // 创建一个非持久化的主题交换机，用来发送通知消息
        return new TopicExchange(mqProperties.getTopicExchangeName());
    }

    @Bean
    public Binding userBinding(Queue userQueue, DirectExchange syncExchange) {
        // 将用户同步队列绑定到点对点的同步交换机
        return BindingBuilder.bind(userQueue).to(syncExchange).with(RoutingKey.MQ_KEY_USER);
    }

    @Bean
    public Binding roomBinding(Queue roomQueue, DirectExchange syncExchange) {
        // 将房间同步队列绑定到点对点的同步交换机
        return BindingBuilder.bind(roomQueue).to(syncExchange).with(RoutingKey.MQ_KEY_ROOM);
    }

    @Bean
    public Binding deviceBinding(Queue deviceQueue, DirectExchange syncExchange) {
        // 将设备同步队列绑定到点对点的同步交换机
        return BindingBuilder.bind(deviceQueue).to(syncExchange).with(RoutingKey.MQ_KEY_DEVICE);
    }

    @Bean
    public Binding hotelBinding(Queue hotelQueue, FanoutExchange noticeExchange) {
        // 将酒店通知队列绑定到广播消息的通知交换机
        return BindingBuilder.bind(hotelQueue).to(noticeExchange);
    }

    @Bean
    public Binding adminBinding(Queue adminQueue, FanoutExchange noticeExchange) {
        // 将管理员通知队列绑定到广播消息的通知交换机
        return BindingBuilder.bind(adminQueue).to(noticeExchange);
    }

    @Bean
    public Binding hotelTopicBinding(Queue hotelQueue, TopicExchange topicExchange) {
        // 将酒店通知队列绑定到主题交换机
        return BindingBuilder.bind(hotelQueue).to(topicExchange).with(RoutingKey.MQ_KEY_HOTEL_TOPIC_NOTICE);
    }

    @Bean
    public Binding adminTopicBinding(Queue adminQueue, TopicExchange topicExchange) {
        // 将管理员通知队列绑定到主题交换机
        return BindingBuilder.bind(adminQueue).to(topicExchange).with(RoutingKey.MQ_KEY_ADMIN_TOPIC_NOTICE);
    }

    /**
     * 如果无需设置消息确认回调等操作，则忽略该配置
     */
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);

        // 设置生产者确认回调
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            String id = "未知的数据标识";
            if (correlationData != null) {
                id = correlationData.getId();
            }
            if (ack) {
                String msg = String.format("消息发送成功: %s", id);
                System.out.println(msg);
            } else {
                String msg = String.format("消息发送失败[%s]: %s", id, cause);
                System.err.println(msg);
            }
        });

        return rabbitTemplate;
    }
}
